home *** CD-ROM | disk | FTP | other *** search
/ Programming a Multiplayer FPS in DirectX / Programming a Multiplayer FPS in DirectX (Companion CD).iso / DirectX / dxsdk_oct2004.exe / dxsdk.exe / Samples / C++ / Direct3D / CustomUI / CustomUI.cpp next >
Encoding:
C/C++ Source or Header  |  2004-09-28  |  37.3 KB  |  770 lines

  1. //--------------------------------------------------------------------------------------
  2. // File: CustomUI.cpp
  3. //
  4. // Starting point for new Direct3D applications
  5. //
  6. // Copyright (c) Microsoft Corporation. All rights reserved.
  7. //--------------------------------------------------------------------------------------
  8. #include "dxstdafx.h"
  9. #include "resource.h"
  10.  
  11. //#define DEBUG_VS   // Uncomment this line to debug vertex shaders 
  12. //#define DEBUG_PS   // Uncomment this line to debug pixel shaders 
  13.  
  14.  
  15. //--------------------------------------------------------------------------------------
  16. // Global variables
  17. //--------------------------------------------------------------------------------------
  18. ID3DXFont*              g_pFont = NULL;         // Font for drawing text
  19. ID3DXSprite*            g_pTextSprite = NULL;   // Sprite for batching draw text calls
  20. ID3DXEffect*            g_pEffect = NULL;       // D3DX effect interface
  21. CDXUTMesh               g_Mesh;                 // Background mesh
  22. D3DXMATRIXA16           g_mView;
  23. CModelViewerCamera      g_Camera;               // A model viewing camera
  24. CDXUTDialog             g_HUD;                  // dialog for standard controls
  25. CDXUTDialog             g_SampleUI;             // dialog for sample specific controls
  26.  
  27.  
  28. //--------------------------------------------------------------------------------------
  29. // UI control IDs
  30. //--------------------------------------------------------------------------------------
  31. #define IDC_TOGGLEFULLSCREEN    1
  32. #define IDC_TOGGLEREF           3
  33. #define IDC_CHANGEDEVICE        4
  34. #define IDC_EDITBOX1            5
  35. #define IDC_EDITBOX2            6
  36. #define IDC_ENABLEIME           7
  37. #define IDC_DISABLEIME          8
  38. #define IDC_COMBOBOX            9
  39. #define IDC_STATIC              10
  40. #define IDC_OUTPUT              12
  41. #define IDC_SLIDER              13
  42. #define IDC_CHECKBOX            14
  43. #define IDC_CLEAREDIT           15
  44. #define IDC_RADIO1A             16
  45. #define IDC_RADIO1B             17
  46. #define IDC_RADIO1C             18
  47. #define IDC_RADIO2A             19
  48. #define IDC_RADIO2B             20
  49. #define IDC_RADIO2C             21
  50. #define IDC_LISTBOX             22
  51. #define IDC_LISTBOXM            23
  52.  
  53.  
  54. //--------------------------------------------------------------------------------------
  55. // Forward declarations 
  56. //--------------------------------------------------------------------------------------
  57. bool    CALLBACK IsDeviceAcceptable( D3DCAPS9* pCaps, D3DFORMAT AdapterFormat, D3DFORMAT BackBufferFormat, bool bWindowed );
  58. void    CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, const D3DCAPS9* pCaps );
  59. HRESULT CALLBACK OnCreateDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc );
  60. HRESULT CALLBACK OnResetDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc );
  61. void    CALLBACK OnFrameMove( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime );
  62. void    CALLBACK OnFrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime );
  63. LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing );
  64. void    CALLBACK KeyboardProc( UINT nChar, bool bKeyDown, bool bAltDown  );
  65. void    CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CDXUTControl* pControl );
  66. void    CALLBACK OnLostDevice();
  67. void    CALLBACK OnDestroyDevice();
  68.  
  69. void    InitApp();
  70. HRESULT LoadMesh( IDirect3DDevice9* pd3dDevice, WCHAR* strFileName, ID3DXMesh** ppMesh );
  71. void    RenderText();
  72.  
  73.  
  74. //--------------------------------------------------------------------------------------
  75. // Entry point to the program. Initializes everything and goes into a message processing 
  76. // loop. Idle time is used to render the scene.
  77. //--------------------------------------------------------------------------------------
  78. INT WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int )
  79. {
  80.     // Set the callback functions. These functions allow the sample framework to notify
  81.     // the application about device changes, user input, and windows messages.  The 
  82.     // callbacks are optional so you need only set callbacks for events you're interested 
  83.     // in. However, if you don't handle the device reset/lost callbacks then the sample 
  84.     // framework won't be able to reset your device since the application must first 
  85.     // release all device resources before resetting.  Likewise, if you don't handle the 
  86.     // device created/destroyed callbacks then the sample framework won't be able to 
  87.     // recreate your device resources.
  88.     DXUTSetCallbackDeviceCreated( OnCreateDevice );
  89.     DXUTSetCallbackDeviceReset( OnResetDevice );
  90.     DXUTSetCallbackDeviceLost( OnLostDevice );
  91.     DXUTSetCallbackDeviceDestroyed( OnDestroyDevice );
  92.     DXUTSetCallbackMsgProc( MsgProc );
  93.     DXUTSetCallbackKeyboard( KeyboardProc );
  94.     DXUTSetCallbackFrameRender( OnFrameRender );
  95.     DXUTSetCallbackFrameMove( OnFrameMove );
  96.  
  97.     // Show the cursor and clip it when in full screen
  98.     DXUTSetCursorSettings( true, true );
  99.  
  100.     InitApp();
  101.  
  102.     // Initialize the sample framework and create the desired Win32 window and Direct3D 
  103.     // device for the application. Calling each of these functions is optional, but they
  104.     // allow you to set several options which control the behavior of the framework.
  105.     DXUTInit( true, true, true ); // Parse the command line, handle the default hotkeys, and show msgboxes
  106.     DXUTCreateWindow( L"CustomUI" );
  107.     DXUTCreateDevice( D3DADAPTER_DEFAULT, true, 640, 480, IsDeviceAcceptable, ModifyDeviceSettings );
  108.  
  109.     // Pass control to the sample framework for handling the message pump and 
  110.     // dispatching render calls. The sample framework will call your FrameMove 
  111.     // and FrameRender callback when there is idle time between handling window messages.
  112.     DXUTMainLoop();
  113.  
  114.     // Perform any application-level cleanup here. Direct3D device resources are released within the
  115.     // appropriate callback functions and therefore don't require any cleanup code here.
  116.  
  117.     return DXUTGetExitCode();
  118. }
  119.  
  120.  
  121. //--------------------------------------------------------------------------------------
  122. // Initialize the app 
  123. //--------------------------------------------------------------------------------------
  124. void InitApp()
  125. {
  126.     // Initialize dialogs
  127.     g_HUD.SetCallback( OnGUIEvent ); int iY = 10; 
  128.     g_HUD.AddButton( IDC_TOGGLEFULLSCREEN, L"Toggle full screen", 35, iY, 125, 22 );
  129.     g_HUD.AddButton( IDC_TOGGLEREF, L"Toggle REF (F3)", 35, iY += 24, 125, 22 );
  130.     g_HUD.AddButton( IDC_CHANGEDEVICE, L"Change device (F2)", 35, iY += 24, 125, 22 );
  131.  
  132.     g_SampleUI.SetCallback( OnGUIEvent );
  133.     g_SampleUI.SetFont( 1, L"Comic Sans MS", 24, FW_NORMAL );
  134.     g_SampleUI.SetFont( 2, L"Courier New", 16, FW_NORMAL );
  135.  
  136.     // Static
  137.     g_SampleUI.AddStatic( IDC_STATIC, L"This is a static control.", 0, 0, 200, 30 );
  138.     g_SampleUI.AddStatic( IDC_OUTPUT, L"This static control provides feedback for your action.  It will change as you interact with the UI controls.", 20, 50, 620, 300 );
  139.     g_SampleUI.GetStatic( IDC_OUTPUT )->SetTextColor( D3DCOLOR_ARGB( 255, 255, 0, 0 ) ); // Change color to red
  140.     g_SampleUI.GetStatic( IDC_STATIC )->SetTextColor( D3DCOLOR_ARGB( 255, 0, 255, 0 ) ); // Change color to green
  141.     g_SampleUI.GetControl( IDC_OUTPUT )->GetElement( 0 )->dwTextFormat = DT_LEFT|DT_TOP|DT_WORDBREAK;
  142.     g_SampleUI.GetControl( IDC_OUTPUT )->GetElement( 0 )->iFont = 2;
  143.     g_SampleUI.GetControl( IDC_STATIC )->GetElement( 0 )->dwTextFormat = DT_CENTER|DT_VCENTER|DT_WORDBREAK;
  144.  
  145.     // Buttons
  146.     g_SampleUI.AddButton( IDC_ENABLEIME, L"Enable IME", 10, 390, 80, 35 );
  147.     g_SampleUI.AddButton( IDC_DISABLEIME, L"Disable IME", 10, 430, 80, 35 );
  148.  
  149.     // Edit box
  150.     g_SampleUI.AddEditBox( IDC_EDITBOX1, L"Edit control with default styles. Type text here and press Enter", 20, 440, 600, 32 );
  151.  
  152.     // IME-enabled edit box
  153.     CDXUTIMEEditBox *pIMEEdit;
  154.     if( SUCCEEDED( g_SampleUI.AddIMEEditBox( IDC_EDITBOX2, L"IME-capable edit control with custom styles. Type and press Enter", 20, 390, 600, 45, false, &pIMEEdit ) ) )
  155.     {
  156.         pIMEEdit->GetElement( 0 )->iFont = 1;
  157.         pIMEEdit->GetElement( 1 )->iFont = 1;
  158.         pIMEEdit->GetElement( 9 )->iFont = 1;
  159.         pIMEEdit->GetElement( 0 )->TextureColor.Init( D3DCOLOR_ARGB( 128, 255, 255, 255 ) );  // Transparent center
  160.         pIMEEdit->SetBorderWidth( 7 );
  161.         pIMEEdit->SetTextColor( D3DCOLOR_ARGB( 255, 64, 64, 64 ) );
  162.         pIMEEdit->SetCaretColor( D3DCOLOR_ARGB( 255, 64, 64, 64 ) );
  163.         pIMEEdit->SetSelectedTextColor( D3DCOLOR_ARGB( 255, 255, 255, 255 ) );
  164.         pIMEEdit->SetSelectedBackColor( D3DCOLOR_ARGB( 255, 40, 72, 72 ) );
  165.     }
  166.  
  167.     // Slider
  168.     g_SampleUI.AddSlider( IDC_SLIDER, 200, 450, 200, 24, 0, 100, 50, false );
  169.  
  170.     // Checkbox
  171.     g_SampleUI.AddCheckBox( IDC_CHECKBOX, L"This is a checkbox with hotkey. Press 'C' to toggle the check state.",
  172.                             150, 450, 350, 24, false, L'C', false );
  173.     g_SampleUI.AddCheckBox( IDC_CLEAREDIT, L"This checkbox controls whether edit control text is cleared when Enter is pressed.",
  174.                             150, 460, 430, 24, false, 0, false );
  175.  
  176.     // Combobox
  177.     CDXUTComboBox *pCombo;
  178.     g_SampleUI.AddComboBox( IDC_COMBOBOX, 0, 0, 200, 24, 0, false, &pCombo );
  179.     if( pCombo )
  180.     {
  181.         pCombo->SetDropHeight( 100 );
  182.         pCombo->AddItem( L"Combobox item", (LPVOID)0x11111111 );
  183.         pCombo->AddItem( L"Placeholder", (LPVOID)0x12121212 );
  184.         pCombo->AddItem( L"One more", (LPVOID)0x13131313 );
  185.         pCombo->AddItem( L"I can't get enough", (LPVOID)0x14141414 );
  186.         pCombo->AddItem( L"Ok, last one, I promise", (LPVOID)0x15151515 );
  187.     }
  188.  
  189.     // Radio buttons
  190.     g_SampleUI.AddRadioButton( IDC_RADIO1A, 1, L"Radio group 1 Amy", 0, 50, 200, 24 );
  191.     g_SampleUI.AddRadioButton( IDC_RADIO1B, 1, L"Radio group 1 Brian", 0, 50, 200, 24 );
  192.     g_SampleUI.AddRadioButton( IDC_RADIO1C, 1, L"Radio group 1 Clark", 0, 50, 200, 24 );
  193.  
  194.     g_SampleUI.AddRadioButton( IDC_RADIO2A, 2, L"Single", 0, 50, 70, 24 );
  195.     g_SampleUI.AddRadioButton( IDC_RADIO2B, 2, L"Double", 0, 50, 70, 24 );
  196.     g_SampleUI.AddRadioButton( IDC_RADIO2C, 2, L"Triple", 0, 50, 70, 24 );
  197.  
  198.     // List box
  199.     g_SampleUI.AddListBox( IDC_LISTBOX, 30, 400, 200, 150, 0 );
  200.     for( int i = 0; i < 15; ++i )
  201.     {
  202.         WCHAR wszText[50];
  203.         swprintf( wszText, L"Single-selection listbox item %d", i );
  204.         g_SampleUI.GetListBox( IDC_LISTBOX )->AddItem( wszText, (LPVOID)(size_t)i );
  205.     }
  206.     g_SampleUI.AddListBox( IDC_LISTBOXM, 30, 400, 200, 150, CDXUTListBox::MULTISELECTION );
  207.     for( int i = 0; i < 30; ++i )
  208.     {
  209.         WCHAR wszText[50];
  210.         swprintf( wszText, L"Multi-selection listbox item %d", i );
  211.         g_SampleUI.GetListBox( IDC_LISTBOXM )->AddItem( wszText, (LPVOID)(size_t)i );
  212.     }
  213. }
  214.  
  215.  
  216. //--------------------------------------------------------------------------------------
  217. // Called during device initialization, this code checks the device for some 
  218. // minimum set of capabilities, and rejects those that don't pass by returning false.
  219. //--------------------------------------------------------------------------------------
  220. bool CALLBACK IsDeviceAcceptable( D3DCAPS9* pCaps, D3DFORMAT AdapterFormat, 
  221.                                   D3DFORMAT BackBufferFormat, bool bWindowed )
  222. {
  223.     // Skip backbuffer formats that don't support alpha blending
  224.     IDirect3D9* pD3D = DXUTGetD3DObject(); 
  225.     if( FAILED( pD3D->CheckDeviceFormat( pCaps->AdapterOrdinal, pCaps->DeviceType,
  226.                     AdapterFormat, D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING, 
  227.                     D3DRTYPE_TEXTURE, BackBufferFormat ) ) )
  228.         return false;
  229.  
  230.     // Must support pixel shader 1.1
  231.     if( pCaps->PixelShaderVersion < D3DPS_VERSION( 1, 1 ) )
  232.         return false;
  233.  
  234.     return true;
  235. }
  236.  
  237.  
  238. //--------------------------------------------------------------------------------------
  239. // This callback function is called immediately before a device is created to allow the 
  240. // application to modify the device settings. The supplied pDeviceSettings parameter 
  241. // contains the settings that the framework has selected for the new device, and the 
  242. // application can make any desired changes directly to this structure.  Note however that 
  243. // the sample framework will not correct invalid device settings so care must be taken 
  244. // to return valid device settings, otherwise IDirect3D9::CreateDevice() will fail.  
  245. //--------------------------------------------------------------------------------------
  246. void CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, const D3DCAPS9* pCaps )
  247. {
  248.     // If device doesn't support HW T&L or doesn't support 1.1 vertex shaders in HW 
  249.     // then switch to SWVP.
  250.     if( (pCaps->DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0 ||
  251.          pCaps->VertexShaderVersion < D3DVS_VERSION(1,1) )
  252.     {
  253.         pDeviceSettings->BehaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
  254.     }
  255.     else
  256.     {
  257.         pDeviceSettings->BehaviorFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
  258.     }
  259.  
  260.     // This application is designed to work on a pure device by not using 
  261.     // IDirect3D9::Get*() methods, so create a pure device if supported and using HWVP.
  262.     if ((pCaps->DevCaps & D3DDEVCAPS_PUREDEVICE) != 0 && 
  263.         (pDeviceSettings->BehaviorFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING) != 0 )
  264.         pDeviceSettings->BehaviorFlags |= D3DCREATE_PUREDEVICE;
  265.  
  266.     // Debugging vertex shaders requires either REF or software vertex processing 
  267.     // and debugging pixel shaders requires REF.  
  268. #ifdef DEBUG_VS
  269.     if( pDeviceSettings->DeviceType != D3DDEVTYPE_REF )
  270.     {
  271.         pDeviceSettings->BehaviorFlags &= ~D3DCREATE_HARDWARE_VERTEXPROCESSING;
  272.         pDeviceSettings->BehaviorFlags &= ~D3DCREATE_PUREDEVICE;                            
  273.         pDeviceSettings->BehaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
  274.     }
  275. #endif
  276. #ifdef DEBUG_PS
  277.     pDeviceSettings->DeviceType = D3DDEVTYPE_REF;
  278. #endif
  279. }
  280.  
  281.  
  282. //--------------------------------------------------------------------------------------
  283. // This callback function will be called immediately after the Direct3D device has been 
  284. // created, which will happen during application initialization and windowed/full screen 
  285. // toggles. This is the best location to create D3DPOOL_MANAGED resources since these 
  286. // resources need to be reloaded whenever the device is destroyed. Resources created  
  287. // here should be released in the OnDestroyDevice callback. 
  288. //--------------------------------------------------------------------------------------
  289. HRESULT CALLBACK OnCreateDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc )
  290. {
  291.     HRESULT hr;
  292.  
  293.     // Initialize the font
  294.     V_RETURN( D3DXCreateFont( pd3dDevice, 15, 0, FW_BOLD, 1, FALSE, DEFAULT_CHARSET, 
  295.                          OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, 
  296.                          L"Arial", &g_pFont ) );
  297.  
  298.     // Define DEBUG_VS and/or DEBUG_PS to debug vertex and/or pixel shaders with the 
  299.     // shader debugger. Debugging vertex shaders requires either REF or software vertex 
  300.     // processing, and debugging pixel shaders requires REF.  The 
  301.     // D3DXSHADER_FORCE_*_SOFTWARE_NOOPT flag improves the debug experience in the 
  302.     // shader debugger.  It enables source level debugging, prevents instruction 
  303.     // reordering, prevents dead code elimination, and forces the compiler to compile 
  304.     // against the next higher available software target, which ensures that the 
  305.     // unoptimized shaders do not exceed the shader model limitations.  Setting these 
  306.     // flags will cause slower rendering since the shaders will be unoptimized and 
  307.     // forced into software.  See the DirectX documentation for more information about 
  308.     // using the shader debugger.
  309.     DWORD dwShaderFlags = 0;
  310.     #ifdef DEBUG_VS
  311.         dwShaderFlags |= D3DXSHADER_FORCE_VS_SOFTWARE_NOOPT;
  312.     #endif
  313.     #ifdef DEBUG_PS
  314.         dwShaderFlags |= D3DXSHADER_FORCE_PS_SOFTWARE_NOOPT;
  315.     #endif
  316.  
  317.     // Read the D3DX effect file
  318.     WCHAR str[MAX_PATH];
  319.     V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, L"CustomUI.fx" ) );
  320.  
  321.     // If this fails, there should be debug output as to 
  322.     // they the .fx file failed to compile
  323.     V_RETURN( D3DXCreateEffectFromFile( pd3dDevice, str, NULL, NULL, dwShaderFlags, 
  324.                                         NULL, &g_pEffect, NULL ) );
  325.  
  326.     g_Mesh.Create( pd3dDevice, L"misc\\cell.x" );
  327.  
  328.     // Setup the camera's view parameters
  329.     D3DXVECTOR3 vecEye(0.0f, 1.5f, -7.0f);
  330.     D3DXVECTOR3 vecAt (0.0f, 0.2f, 0.0f);
  331.     D3DXVECTOR3 vecUp (0.0f, 1.0f, 0.0f );
  332.     g_Camera.SetViewParams( &vecEye, &vecAt );
  333.     D3DXMatrixLookAtLH( &g_mView, &vecEye, &vecAt, &vecUp );
  334.  
  335.     return S_OK;
  336. }
  337.  
  338.  
  339. //--------------------------------------------------------------------------------------
  340. // This function loads the mesh and ensures the mesh has normals; it also optimizes the 
  341. // mesh for the graphics card's vertex cache, which improves performance by organizing 
  342. // the internal triangle list for less cache misses.
  343. //--------------------------------------------------------------------------------------
  344. HRESULT LoadMesh( IDirect3DDevice9* pd3dDevice, WCHAR* strFileName, ID3DXMesh** ppMesh )
  345. {
  346.     ID3DXMesh* pMesh = NULL;
  347.     WCHAR str[MAX_PATH];
  348.     HRESULT hr;
  349.  
  350.     // Load the mesh with D3DX and get back a ID3DXMesh*.  For this
  351.     // sample we'll ignore the X file's embedded materials since we know 
  352.     // exactly the model we're loading.  See the mesh samples such as
  353.     // "OptimizedMesh" for a more generic mesh loading example.
  354.     V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, strFileName ) );
  355.  
  356.     V_RETURN( D3DXLoadMeshFromX(str, D3DXMESH_MANAGED, pd3dDevice, NULL, NULL, NULL, NULL, &pMesh) );
  357.  
  358.     DWORD *rgdwAdjacency = NULL;
  359.  
  360.     // Make sure there are normals which are required for lighting
  361.     if( !(pMesh->GetFVF() & D3DFVF_NORMAL) )
  362.     {
  363.         ID3DXMesh* pTempMesh;
  364.         V( pMesh->CloneMeshFVF( pMesh->GetOptions(), 
  365.                                   pMesh->GetFVF() | D3DFVF_NORMAL, 
  366.                                   pd3dDevice, &pTempMesh ) );
  367.         V( D3DXComputeNormals( pTempMesh, NULL ) );
  368.  
  369.         SAFE_RELEASE( pMesh );
  370.         pMesh = pTempMesh;
  371.     }
  372.  
  373.     // Optimize the mesh for this graphics card's vertex cache 
  374.     // so when rendering the mesh's triangle list the vertices will 
  375.     // cache hit more often so it won't have to re-execute the vertex shader 
  376.     // on those vertices so it will improve perf.     
  377.     rgdwAdjacency = new DWORD[pMesh->GetNumFaces() * 3];
  378.     if( rgdwAdjacency == NULL )
  379.         return E_OUTOFMEMORY;
  380.     V( pMesh->ConvertPointRepsToAdjacency(NULL, rgdwAdjacency) );
  381.     V( pMesh->OptimizeInplace(D3DXMESHOPT_VERTEXCACHE, rgdwAdjacency, NULL, NULL, NULL) );
  382.     delete []rgdwAdjacency;
  383.  
  384.     *ppMesh = pMesh;
  385.  
  386.     return S_OK;
  387. }
  388.  
  389.  
  390. //--------------------------------------------------------------------------------------
  391. // This callback function will be called immediately after the Direct3D device has been 
  392. // reset, which will happen after a lost device scenario. This is the best location to 
  393. // create D3DPOOL_DEFAULT resources since these resources need to be reloaded whenever 
  394. // the device is lost. Resources created here should be released in the OnLostDevice 
  395. // callback. 
  396. //--------------------------------------------------------------------------------------
  397. HRESULT CALLBACK OnResetDevice( IDirect3DDevice9* pd3dDevice, 
  398.                                 const D3DSURFACE_DESC* pBackBufferSurfaceDesc )
  399. {
  400.     HRESULT hr;
  401.  
  402.     if( g_pFont )
  403.         V_RETURN( g_pFont->OnResetDevice() );
  404.     if( g_pEffect )
  405.         V_RETURN( g_pEffect->OnResetDevice() );
  406.  
  407.     // Create a sprite to help batch calls when drawing many lines of text
  408.     V_RETURN( D3DXCreateSprite( pd3dDevice, &g_pTextSprite ) );
  409.  
  410.     // Setup the camera's projection parameters
  411.     float fAspectRatio = pBackBufferSurfaceDesc->Width / (FLOAT)pBackBufferSurfaceDesc->Height;
  412.     g_Camera.SetProjParams( D3DX_PI/4, fAspectRatio, 0.1f, 1000.0f );
  413.     g_Camera.SetWindow( pBackBufferSurfaceDesc->Width, pBackBufferSurfaceDesc->Height );
  414.  
  415.     g_HUD.SetLocation( pBackBufferSurfaceDesc->Width-170, 0 );
  416.     g_HUD.SetSize( 170, 170 );
  417.     g_SampleUI.SetLocation( 0, 0 );
  418.     g_SampleUI.SetSize( pBackBufferSurfaceDesc->Width, pBackBufferSurfaceDesc->Height );
  419.  
  420.     g_SampleUI.GetControl( IDC_STATIC )->SetSize( pBackBufferSurfaceDesc->Width, pBackBufferSurfaceDesc->Height * 6 / 10 );
  421.     g_SampleUI.GetControl( IDC_OUTPUT )->SetSize( pBackBufferSurfaceDesc->Width - 170, pBackBufferSurfaceDesc->Height / 4 );
  422.     g_SampleUI.GetControl( IDC_EDITBOX1 )->SetLocation( 20, pBackBufferSurfaceDesc->Height - 230 );
  423.     g_SampleUI.GetControl( IDC_EDITBOX1 )->SetSize( pBackBufferSurfaceDesc->Width - 40, 32 );
  424.     g_SampleUI.GetControl( IDC_EDITBOX2 )->SetLocation( 20, pBackBufferSurfaceDesc->Height - 280 );
  425.     g_SampleUI.GetControl( IDC_EDITBOX2 )->SetSize( pBackBufferSurfaceDesc->Width - 40, 45 );
  426.     g_SampleUI.GetControl( IDC_ENABLEIME )->SetLocation( 110, pBackBufferSurfaceDesc->Height - 80 );
  427.     g_SampleUI.GetControl( IDC_DISABLEIME )->SetLocation( 200, pBackBufferSurfaceDesc->Height - 80 );
  428.     g_SampleUI.GetControl( IDC_SLIDER )->SetLocation( 10, pBackBufferSurfaceDesc->Height - 140 );
  429.     g_SampleUI.GetControl( IDC_CHECKBOX )->SetLocation( 100, pBackBufferSurfaceDesc->Height - 50 );
  430.     g_SampleUI.GetControl( IDC_CLEAREDIT )->SetLocation( 100, pBackBufferSurfaceDesc->Height - 25 );
  431.     g_SampleUI.GetControl( IDC_COMBOBOX )->SetLocation( 20, pBackBufferSurfaceDesc->Height - 180 );
  432.     g_SampleUI.GetControl( IDC_RADIO1A )->SetLocation( pBackBufferSurfaceDesc->Width - 140, 100 );
  433.     g_SampleUI.GetControl( IDC_RADIO1B )->SetLocation( pBackBufferSurfaceDesc->Width - 140, 124 );
  434.     g_SampleUI.GetControl( IDC_RADIO1C )->SetLocation( pBackBufferSurfaceDesc->Width - 140, 148 );
  435.     g_SampleUI.GetControl( IDC_RADIO2A )->SetLocation( 20, pBackBufferSurfaceDesc->Height - 100 );
  436.     g_SampleUI.GetControl( IDC_RADIO2B )->SetLocation( 20, pBackBufferSurfaceDesc->Height - 76 );
  437.     g_SampleUI.GetControl( IDC_RADIO2C )->SetLocation( 20, pBackBufferSurfaceDesc->Height - 52 );
  438.     g_SampleUI.GetControl( IDC_LISTBOX )->SetLocation( pBackBufferSurfaceDesc->Width - 400, pBackBufferSurfaceDesc->Height - 180 );
  439.     g_SampleUI.GetControl( IDC_LISTBOX )->SetSize( 190, 96 );
  440.     g_SampleUI.GetControl( IDC_LISTBOXM )->SetLocation( pBackBufferSurfaceDesc->Width - 200, pBackBufferSurfaceDesc->Height - 180 );
  441.     g_SampleUI.GetControl( IDC_LISTBOXM )->SetSize( 190, 124 );
  442.     g_Mesh.RestoreDeviceObjects( pd3dDevice );
  443.  
  444.     return S_OK;
  445. }
  446.  
  447.  
  448. //--------------------------------------------------------------------------------------
  449. // This callback function will be called once at the beginning of every frame. This is the
  450. // best location for your application to handle updates to the scene, but is not 
  451. // intended to contain actual rendering calls, which should instead be placed in the 
  452. // OnFrameRender callback.  
  453. //--------------------------------------------------------------------------------------
  454. void CALLBACK OnFrameMove( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime )
  455. {
  456.     D3DXMATRIXA16 m;
  457.     D3DXMatrixRotationY( &m, D3DX_PI * fElapsedTime / 40.0f );
  458.     D3DXMatrixMultiply( &g_mView, &m, &g_mView );
  459. }
  460.  
  461.  
  462. //--------------------------------------------------------------------------------------
  463. // This callback function will be called at the end of every frame to perform all the 
  464. // rendering calls for the scene, and it will also be called if the window needs to be 
  465. // repainted. After this function has returned, the sample framework will call 
  466. // IDirect3DDevice9::Present to display the contents of the next buffer in the swap chain
  467. //--------------------------------------------------------------------------------------
  468. void CALLBACK OnFrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime )
  469. {
  470.     HRESULT hr;
  471.     D3DXMATRIXA16 mWorld;
  472.     D3DXMATRIXA16 mView;
  473.     D3DXMATRIXA16 mProj;
  474.     D3DXMATRIXA16 mWorldViewProjection;
  475.     
  476.     // Clear the render target and the zbuffer 
  477.     V( pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(0, 45, 50, 170), 1.0f, 0) );
  478.  
  479.     // Render the scene
  480.     if( SUCCEEDED( pd3dDevice->BeginScene() ) )
  481.     {
  482.         // Get the projection & view matrix from the camera class
  483.         mWorld = *g_Camera.GetWorldMatrix();       
  484.         mProj = *g_Camera.GetProjMatrix();       
  485.         mView = g_mView;
  486.  
  487.         mWorldViewProjection = mWorld * mView * mProj;
  488.  
  489.         // Update the effect's variables.  Instead of using strings, it would 
  490.         // be more efficient to cache a handle to the parameter by calling 
  491.         // ID3DXEffect::GetParameterByName
  492.         V( g_pEffect->SetMatrix( "g_mWorldViewProjection", &mWorldViewProjection ) );
  493.         V( g_pEffect->SetMatrix( "g_mWorld", &mWorld ) );
  494.         V( g_pEffect->SetFloat( "g_fTime", (float)fTime ) );
  495.  
  496.         g_pEffect->SetTechnique( "RenderScene" );
  497.         UINT cPasses;
  498.         g_pEffect->Begin( &cPasses, 0 );
  499.         ID3DXMesh *pMesh = g_Mesh.GetLocalMesh();
  500.         for( UINT p = 0; p < cPasses; ++p )
  501.         {
  502.             g_pEffect->BeginPass( p );
  503.             for( UINT m = 0; m < g_Mesh.m_dwNumMaterials; ++m )
  504.             {
  505.                 g_pEffect->SetTexture( "g_txScene", g_Mesh.m_pTextures[m] );
  506.                 g_pEffect->CommitChanges();
  507.                 pMesh->DrawSubset( m );
  508.             }
  509.             g_pEffect->EndPass();
  510.         }
  511.         g_pEffect->End();
  512.  
  513.         RenderText();
  514.         V( g_HUD.OnRender( fElapsedTime ) );
  515.         V( g_SampleUI.OnRender( fElapsedTime ) );
  516.  
  517.         V( pd3dDevice->EndScene() );
  518.     }
  519. }
  520.  
  521.  
  522. //--------------------------------------------------------------------------------------
  523. // Render the help and statistics text. This function uses the ID3DXFont interface for 
  524. // efficient text rendering.
  525. //--------------------------------------------------------------------------------------
  526. void RenderText()
  527. {
  528.     // The helper object simply helps keep track of text position, and color
  529.     // and then it calls pFont->DrawText( m_pSprite, strMsg, -1, &rc, DT_NOCLIP, m_clr );
  530.     // If NULL is passed in as the sprite object, then it will work however the 
  531.     // pFont->DrawText() will not be batched together.  Batching calls will improves performance.
  532.     CDXUTTextHelper txtHelper( g_pFont, g_pTextSprite, 15 );
  533.  
  534.     // Output statistics
  535.     txtHelper.Begin();
  536.     txtHelper.SetInsertionPos( 5, 5 );
  537.     txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 0.0f, 1.0f ) );
  538.     txtHelper.DrawTextLine( DXUTGetFrameStats() );
  539.     txtHelper.DrawTextLine( DXUTGetDeviceStats() );
  540.  
  541.     txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f ) );
  542.     
  543.     // Draw help
  544.     txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f ) );
  545.     txtHelper.DrawTextLine( L"Press ESC to quit" );
  546.     txtHelper.End();
  547. }
  548.  
  549.  
  550. //--------------------------------------------------------------------------------------
  551. // Before handling window messages, the sample framework passes incoming windows 
  552. // messages to the application through this callback function. If the application sets 
  553. // *pbNoFurtherProcessing to TRUE, then the sample framework will not process this message.
  554. //--------------------------------------------------------------------------------------
  555. LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing )
  556. {
  557.     // Give the dialogs a chance to handle the message first
  558.     *pbNoFurtherProcessing = g_HUD.MsgProc( hWnd, uMsg, wParam, lParam );
  559.     if( *pbNoFurtherProcessing )
  560.         return 0;
  561.     *pbNoFurtherProcessing = g_SampleUI.MsgProc( hWnd, uMsg, wParam, lParam );
  562.     if( *pbNoFurtherProcessing )
  563.         return 0;
  564.  
  565.     // Pass all remaining windows messages to camera so it can respond to user input
  566.     g_Camera.HandleMessages( hWnd, uMsg, wParam, lParam );
  567.  
  568.     return 0;
  569. }
  570.  
  571.  
  572. //--------------------------------------------------------------------------------------
  573. // As a convenience, the sample framework inspects the incoming windows messages for
  574. // keystroke messages and decodes the message parameters to pass relevant keyboard
  575. // messages to the application.  The framework does not remove the underlying keystroke 
  576. // messages, which are still passed to the application's MsgProc callback.
  577. //--------------------------------------------------------------------------------------
  578. void CALLBACK KeyboardProc( UINT nChar, bool bKeyDown, bool bAltDown )
  579. {
  580. }
  581.  
  582.  
  583. //--------------------------------------------------------------------------------------
  584. // Handles the GUI events
  585. //--------------------------------------------------------------------------------------
  586. void CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CDXUTControl* pControl )
  587. {
  588.     WCHAR wszOutput[1024];
  589.  
  590.     switch( nControlID )
  591.     {
  592.         case IDC_TOGGLEFULLSCREEN: DXUTToggleFullScreen(); break;
  593.         case IDC_TOGGLEREF:        DXUTToggleREF(); break;
  594.         case IDC_CHANGEDEVICE:     DXUTSetShowSettingsDialog( !DXUTGetShowSettingsDialog() ); break;
  595.         case IDC_ENABLEIME:
  596.             CDXUTIMEEditBox::EnableImeSystem( true );
  597.             g_SampleUI.GetStatic( IDC_OUTPUT )->SetText( L"You clicked the 'Enable IME' button.\nIME text input is enabled for IME-capable edit controls." );
  598.             break;
  599.         case IDC_DISABLEIME:
  600.             CDXUTIMEEditBox::EnableImeSystem( false );
  601.             g_SampleUI.GetStatic( IDC_OUTPUT )->SetText( L"You clicked the 'Disable IME' button.\nIME text input is disabled for IME-capable edit controls." );
  602.             break;
  603.         case IDC_EDITBOX1:
  604.         case IDC_EDITBOX2:
  605.             switch( nEvent )
  606.             {
  607.                 case EVENT_EDITBOX_STRING:
  608.                 {
  609.                     _snwprintf( wszOutput, 1024, L"You have pressed Enter in edit control (ID %u).\nThe content of the edit control is:\n\"%s\"",
  610.                                 nControlID, ((CDXUTEditBox*)pControl)->GetText() );
  611.                     wszOutput[1023] = 0;
  612.                     g_SampleUI.GetStatic( IDC_OUTPUT )->SetText( wszOutput );
  613.  
  614.                     // Clear the text if needed
  615.                     if( g_SampleUI.GetCheckBox( IDC_CLEAREDIT )->GetChecked() )
  616.                         ((CDXUTEditBox*)pControl)->SetText( L"" );
  617.                     break;
  618.                 }
  619.  
  620.                 case EVENT_EDITBOX_CHANGE:
  621.                 {
  622.                     _snwprintf( wszOutput, 1024, L"You have changed the content of an edit control (ID %u).\nIt is now:\n\"%s\"",
  623.                                 nControlID, ((CDXUTEditBox*)pControl)->GetText() );
  624.                     wszOutput[1023] = 0;
  625.                     g_SampleUI.GetStatic( IDC_OUTPUT )->SetText( wszOutput );
  626.  
  627.                     break;
  628.                 }
  629.             }
  630.             break;
  631.         case IDC_SLIDER:
  632.             _snwprintf( wszOutput, 1024, L"You adjusted the slider control.\nThe new value reported is %d",
  633.                         ((CDXUTSlider*)pControl)->GetValue() );
  634.             wszOutput[1023] = L'\0';
  635.             g_SampleUI.GetStatic( IDC_OUTPUT )->SetText( wszOutput );
  636.             break;
  637.         case IDC_CHECKBOX:
  638.             _snwprintf( wszOutput, 1024, L"You %s the upper check box.",
  639.                 ((CDXUTCheckBox*)pControl)->GetChecked() ? L"checked" : L"cleared" );
  640.             wszOutput[1023] = L'\0';
  641.             g_SampleUI.GetStatic( IDC_OUTPUT )->SetText( wszOutput );
  642.             break;
  643.         case IDC_CLEAREDIT:
  644.             _snwprintf( wszOutput, 1024, L"You %s the lower check box.\nNow edit controls will %s",
  645.                         ((CDXUTCheckBox*)pControl)->GetChecked() ? L"checked" : L"cleared",
  646.                         ((CDXUTCheckBox*)pControl)->GetChecked() ? L"be cleared when you press Enter to send the text" : L"retain the text context when you press Enter to send the text" );
  647.             wszOutput[1023] = L'\0';
  648.             g_SampleUI.GetStatic( IDC_OUTPUT )->SetText( wszOutput );
  649.             break;
  650.         case IDC_COMBOBOX:
  651.         {
  652.             DXUTComboBoxItem *pItem = ((CDXUTComboBox*)pControl)->GetSelectedItem();
  653.             _snwprintf( wszOutput, 1024, L"You selected a new item in the combobox.\nThe new item is \"%s\" and the associated data value is 0x%p",
  654.                         pItem->strText, pItem->pData );
  655.             wszOutput[1023] = L'\0';
  656.             g_SampleUI.GetStatic( IDC_OUTPUT )->SetText( wszOutput );
  657.             break;
  658.         }
  659.         case IDC_RADIO1A:
  660.         case IDC_RADIO1B:
  661.         case IDC_RADIO1C:
  662.             _snwprintf( wszOutput, 1024, L"You selected a new radio button in the UPPER radio group.\nThe new button is \"%s\"",
  663.                 ((CDXUTRadioButton*)pControl)->GetText() );
  664.             wszOutput[1023] = L'\0';
  665.             g_SampleUI.GetStatic( IDC_OUTPUT )->SetText( wszOutput );
  666.             break;
  667.         case IDC_RADIO2A:
  668.         case IDC_RADIO2B:
  669.         case IDC_RADIO2C:
  670.             _snwprintf( wszOutput, 1024, L"You selected a new radio button in the LOWER radio group.\nThe new button is \"%s\"",
  671.                 ((CDXUTRadioButton*)pControl)->GetText() );
  672.             wszOutput[1023] = L'\0';
  673.             g_SampleUI.GetStatic( IDC_OUTPUT )->SetText( wszOutput );
  674.             break;
  675.  
  676.         case IDC_LISTBOX:
  677.             switch( nEvent )
  678.             {
  679.                 case EVENT_LISTBOX_ITEM_DBLCLK:
  680.                 {
  681.                     DXUTListBoxItem *pItem = ((CDXUTListBox *)pControl)->GetItem( ((CDXUTListBox *)pControl)->GetSelectedIndex( -1 ) );
  682.  
  683.                     _snwprintf( wszOutput, 1024, L"You double clicked an item in the left list box.  The item is\n\"%s\"",
  684.                         pItem ? pItem->strText : L"" );
  685.                     wszOutput[1023] = L'\0';
  686.                     g_SampleUI.GetStatic( IDC_OUTPUT )->SetText( wszOutput );
  687.                     break;
  688.                 }
  689.  
  690.                 case EVENT_LISTBOX_SELECTION:
  691.                 {
  692.                     _snwprintf( wszOutput, 1024, L"You changed the selection in the left list box.  The selected item is %d", ((CDXUTListBox *)pControl)->GetSelectedIndex() );
  693.                     wszOutput[1023] = L'\0';
  694.                     g_SampleUI.GetStatic( IDC_OUTPUT )->SetText( wszOutput );
  695.                     break;
  696.                 }
  697.             }
  698.             break;
  699.  
  700.         case IDC_LISTBOXM:
  701.             switch( nEvent )
  702.             {
  703.                 case EVENT_LISTBOX_ITEM_DBLCLK:
  704.                 {
  705.                     DXUTListBoxItem *pItem = ((CDXUTListBox *)pControl)->GetItem( ((CDXUTListBox *)pControl)->GetSelectedIndex( -1 ) );
  706.  
  707.                     _snwprintf( wszOutput, 1024, L"You double clicked an item in the right list box.  The item is\n\"%s\"",
  708.                         pItem ? pItem->strText : L"" );
  709.                     wszOutput[1023] = L'\0';
  710.                     g_SampleUI.GetStatic( IDC_OUTPUT )->SetText( wszOutput );
  711.                     break;
  712.                 }
  713.  
  714.                 case EVENT_LISTBOX_SELECTION:
  715.                 {
  716.                     _snwprintf( wszOutput, 1024, L"You changed the selection in the right list box.  The selected item(s) are\n" );
  717.                     wszOutput[1023] = L'\0';
  718.                     int nSelected = -1;
  719.                     while( ( nSelected = ((CDXUTListBox *)pControl)->GetSelectedIndex( nSelected ) ) != -1 )
  720.                     {
  721.                         _snwprintf( wszOutput + lstrlenW( wszOutput ), 1024 - lstrlenW( wszOutput ), L"%d,", nSelected );
  722.                     }
  723.                     // Remove the trailing comma if one exists.
  724.                     if( wszOutput[lstrlenW(wszOutput)-1] == L',' )
  725.                         wszOutput[lstrlenW(wszOutput)-1] = L'\0';
  726.                     g_SampleUI.GetStatic( IDC_OUTPUT )->SetText( wszOutput );
  727.                     break;
  728.                 }
  729.             }
  730.             break;
  731.     }
  732. }
  733.  
  734.  
  735. //--------------------------------------------------------------------------------------
  736. // This callback function will be called immediately after the Direct3D device has 
  737. // entered a lost state and before IDirect3DDevice9::Reset is called. Resources created
  738. // in the OnResetDevice callback should be released here, which generally includes all 
  739. // D3DPOOL_DEFAULT resources. See the "Lost Devices" section of the documentation for 
  740. // information about lost devices.
  741. //--------------------------------------------------------------------------------------
  742. void CALLBACK OnLostDevice()
  743. {
  744.     g_Mesh.InvalidateDeviceObjects();
  745.  
  746.     if( g_pFont )
  747.         g_pFont->OnLostDevice();
  748.     if( g_pEffect )
  749.         g_pEffect->OnLostDevice();
  750.     SAFE_RELEASE(g_pTextSprite);
  751. }
  752.  
  753.  
  754. //--------------------------------------------------------------------------------------
  755. // This callback function will be called immediately after the Direct3D device has 
  756. // been destroyed, which generally happens as a result of application termination or 
  757. // windowed/full screen toggles. Resources created in the OnCreateDevice callback 
  758. // should be released here, which generally includes all D3DPOOL_MANAGED resources. 
  759. //--------------------------------------------------------------------------------------
  760. void CALLBACK OnDestroyDevice()
  761. {
  762.     g_Mesh.Destroy();
  763.  
  764.     SAFE_RELEASE(g_pEffect);
  765.     SAFE_RELEASE(g_pFont);
  766. }
  767.  
  768.  
  769.  
  770.